#include "StdAfx.h"
#include "OutputWindow.h"
#include "Resource.h"

#include "ItemSizeManager.h"
CItemSizeManager g_SizeManager;

COutputWindow::COutputWindow(void)
{
}

COutputWindow::~COutputWindow(void)
{
}

INT_PTR COutputWindow::DialogProc( HWND hwndDlg,
								UINT uMsg,
								WPARAM wParam,
								LPARAM lParam)
{
	char Buffer[MAX_BUFFER_SIZE + 2];
	memset(Buffer, 0, sizeof(Buffer));

	switch (uMsg)
	{
	case WM_INITDIALOG:
		{
			SetFocus(hwndDlg);

			// For items' resize funciton
			g_SizeManager.AddItem(IDC_EDIT_LOG, CItemSizeManager::ANCHOR_ALL);
			g_SizeManager.AddItem(IDCANCEL, CItemSizeManager::ANCHOR_BOTTOM_RIGHT);
			g_SizeManager.AddItem(IDC_BUTTON_CLEAN, CItemSizeManager::ANCHOR_BOTTOM_RIGHT);
			g_SizeManager.AddItem(IDOK, CItemSizeManager::ANCHOR_BOTTOM_RIGHT);
			g_SizeManager.Initialize(hwndDlg);
		}
		return TRUE;

	case WM_COMMAND:
		{
			switch(wParam)
			{
			case IDOK:
					// g_SizeManager.UnInitialize();
					// EndDialog(hwndDlg, 0);
					::ShowWindow(hwndDlg, SW_HIDE);
				break;

			case IDCANCEL:
					// g_SizeManager.UnInitialize();
					// EndDialog(hwndDlg, 0);
					::ShowWindow(hwndDlg, SW_HIDE);
				break;

			case IDC_BUTTON_CLEAN:
				{
					// Clean window's text
					if (::IsWindow(hwndDlg))
					{
						HWND hEdit = ::GetDlgItem(hwndDlg, IDC_EDIT_LOG);
						if ((hEdit != NULL) && ::IsWindow(hEdit))
						{
							SendMessage(hEdit, EM_SETSEL, 0, -1);
							SendMessage(hEdit, EM_REPLACESEL, FALSE, reinterpret_cast<LPARAM>(L"\0"));
						}
					}
				}
				break;

			default:
				switch(HIWORD(wParam))
				{
					case EN_MAXTEXT:
					{
						if (LOWORD(wParam) == IDC_EDIT_LOG)
						{
							HWND hwndEditCtrl = reinterpret_cast<HWND>(lParam);
							if ((hwndEditCtrl != NULL) && ::IsWindow(hwndEditCtrl))
							{
								SendMessage(hwndEditCtrl, EM_SETSEL, 0, -1);
								SendMessage(hwndEditCtrl, EM_REPLACESEL, FALSE, reinterpret_cast<LPARAM>(L"\0"));
							}
						}
					}
					break;

				} // switch(HIWORD(wParam))

			} // switch(wParam)
		}
		return TRUE;

	case WM_SIZE:
		{
			// Specifies the type of resizing requested.
			switch(wParam)
			{
			case SIZE_MAXHIDE:		// Message is sent to all pop-up windows when
									// some other window is maximized.
			case SIZE_MAXSHOW:		// Message is sent to all pop-up windows when
									// some other window has been restored to its former size.
			case SIZE_MINIMIZED:	// The window has been minimized.
				break;

			case SIZE_MAXIMIZED:	// The window has been maximized.
			case SIZE_RESTORED:		// The window has been resized, but neither
									// the SIZE_MINIMIZED nor SIZE_MAXIMIZED value applies.
				{
					SIZE WndSize;
					// The low-order word of lParam specifies the new width of the client area. 
					WndSize.cx = LOWORD(lParam);
					// The high-order word of lParam specifies the new height of the client area. 
					WndSize.cy = HIWORD(lParam);
					ResizeWindow(hwndDlg, WndSize);
				}
				break;

			} // switch(wParam)
		}
		return TRUE;

	case WM_WRITE_LOG:
		{
			if (lParam <= MAX_BUFFER_SIZE)
			{
				memcpy(Buffer, reinterpret_cast<const void *>(wParam), lParam);
				Buffer[lParam] = 0;
				Buffer[lParam + 1] = 0;
				AppendLog(hwndDlg, Buffer, (const unsigned int)lParam);
			}
			else
			{
				PBYTE pBuffer = reinterpret_cast<PBYTE>(malloc(lParam + 2));
				if (pBuffer != NULL)
				{
					memcpy(pBuffer, reinterpret_cast<const void *>(wParam), lParam);
					pBuffer[lParam] = 0;
					pBuffer[lParam + 1] = 0;

					AppendLog(hwndDlg, Buffer, (const unsigned int)lParam);

					free(pBuffer);
				}
			}
		}

		return TRUE;
	} // switch (uMsg)

	return FALSE;
}

HWND COutputWindow::CreateOutputWindow(	HINSTANCE hInstance,
										HWND hWndParent)
{
	return ::CreateDialog( hInstance,
							MAKEINTRESOURCE(IDD_DIALOG_LOG_WINDOW),
							hWndParent,
							COutputWindow::DialogProc);
}

void COutputWindow::ResizeWindow(HWND hDlg, SIZE &WndSize)
{
	if (!::IsWindow(hDlg))
	{
		return;
	}

	g_SizeManager.OnSize(hDlg, WndSize);
}

void COutputWindow::AppendLog(	HWND hDlg,
								LPCSTR lpszLog,
								const unsigned int nLength)
{
	if (!::IsWindow(hDlg))
	{
		return;
	}

	HWND hEdit = ::GetDlgItem(hDlg, IDC_EDIT_LOG);
	if ((hEdit != NULL) && ::IsWindow(hEdit))
	{
		// Select end of edit box
		SendMessage(hEdit, EM_SETSEL, -1, 0);

		// Convert multi char string to wide char string
		if (nLength <= MAX_BUFFER_SIZE)
		{
			WCHAR Buffer[MAX_BUFFER_SIZE + 1];
			int nRet = ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, lpszLog, nLength, Buffer, MAX_BUFFER_SIZE);
			if (nRet > 0)
			{
				Buffer[nRet] = 0;
				SendMessage(hEdit, EM_REPLACESEL, FALSE, reinterpret_cast<LPARAM>(Buffer));
			}
		}
		else
		{
			WCHAR * Buffer = new WCHAR[nLength + 1];
			if (Buffer != NULL)
			{
				int nRet = ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, lpszLog, nLength, Buffer, MAX_BUFFER_SIZE);
				if (nRet > 0)
				{
					Buffer[nRet] = 0;
					SendMessage(hEdit, EM_REPLACESEL, FALSE, reinterpret_cast<LPARAM>(Buffer));
				}
			}
		}
	}
}